<script lang="ts">
export default {
  name: 'HmiParse'
}
</script>

<script setup lang="ts">
import { ref, shallowRef } from 'vue'
import {
  ElMessage,
  genFileId,
  type UploadProps,
  type UploadRawFile,
  type UploadUserFile,
  type UploadInstance
} from 'element-plus'
import { defaultProtocolConfig, type ExcelColumnData } from '@/types/hmi/ExcelColumnConfig'
import { read, utils } from 'xlsx'
import { type President } from '@/types/hmi/President'
import useExcelImport, { type TableColumn } from '@/hooks/UseExcelImport'

let emits = defineEmits<{
  /**
   * 解析完成事件
   * @param e 事件名
   * @param data 解析结果
   * @param columns 解析列
   */
  (e: 'parsed', data: ExcelColumnData[] | undefined, columns: TableColumn[]): void
}>()

// 上传组件
const upload = ref<UploadInstance>()
// 读取Excel列的配置组件
const excelColumnConfigInstance = ref()

// 上传文件
const fileList = ref<UploadUserFile[]>([])
const result = shallowRef<ExcelColumnData[]>([])

// Excel读取列配置弹窗开关
const protocolConfigDialog = ref<boolean>(false)
// 解析中 loading 效果
const parseLoading = ref<boolean>(false)

// excel 导入配置hooks
const { configs, addConfig, columns } = useExcelImport({
  defaultOptions: defaultProtocolConfig
})

// 文件选中处理
const handleExceed: UploadProps['onExceed'] = (files) => {
  upload.value!.clearFiles()
  const file = files[0] as UploadRawFile
  file.uid = genFileId()
  upload.value!.handleStart(file)
}

const prepareToParse = () => {
  if (fileList.value.length === 0) {
    ElMessage.warning({ message: '文件为空', grouping: true })
    return
  }

  protocolConfigDialog.value = true
}

// excel 解析处理
const parseXlsx = async () => {
  parseLoading.value = true

  try {
    let file = fileList.value[0]

    let ab = await file.raw?.arrayBuffer()
    let workBook = read(ab)
    let sheet = workBook.Sheets[workBook.SheetNames[0]]
    let excelBeanList: President[] = utils.sheet_to_json<President>(sheet)

    if (!excelBeanList || excelBeanList.length <= 0) {
      return new Error('解析结果为空')
    }

    let excelColumnDataList = excelBeanList.map((bean: President) => {
      let temp: { [key: string]: any } = {}
      columns.value.map((column: TableColumn) => {
        temp[column.key] = bean[column.key]
      })
      return temp
    }) as unknown as ExcelColumnData[]
    Object.freeze(excelColumnDataList)

    result.value = excelColumnDataList
    protocolConfigDialog.value = false
  } catch (e: any) {
    ElMessage.error(`Excel 解析出现异常 ${e.message}`)
  } finally {
    parseLoading.value = false
  }
}

// 确认解析结果
const commitParseResult = () => {
  emits('parsed', result.value, columns.value)
}
</script>

<template>
  <div class="p-2 gap-2">
    <el-card body-class="flex flex-row gap-2 max-h-96">
      <el-upload
        class="grow"
        ref="upload"
        v-model:file-list="fileList"
        drag
        :auto-upload="false"
        :limit="1"
        accept=".xlsx,.xls"
        :on-exceed="handleExceed"
        :show-file-list="false"
      >
        <div class="flex-row-common gap-2">
          <span class="relic-iconfont relic-icon-shangchuan text-3xl" />
          <div v-if="fileList.length>0" class="flex flex-row gap-2 justify-center">
            <div v-for="file in fileList" :key="file.name">
              <span>{{ file.name }}</span>
            </div>
          </div>
        </div>
      </el-upload>
      <div>
        <el-button class="self-center !h-full" type="primary" @click="prepareToParse">开始解析</el-button>
      </div>
    </el-card>
    <el-card class="mt-2">
      <template #header>
        <div class="flex flex-row-reverse">
          <el-button-group>
            <el-button type="primary" @click="commitParseResult">确认无误</el-button>
          </el-button-group>
        </div>
      </template>
      <div style="height: 60vh;">
        <el-auto-resizer>
          <template #default="{ height,width }">
            <el-table-v2 :data="result" :columns="columns"
                         :width="width" :height="height" />
          </template>
        </el-auto-resizer>
      </div>
    </el-card>
    <el-dialog
      ref="excelColumnConfigInstance"
      v-model="protocolConfigDialog"
      width="80vw"
    >
      <el-table :data="configs" border>
        <el-table-column prop="label" label="名称">
          <template #default="scope">
            <el-input v-if="scope.row.labelEditable" v-model="scope.row.label" />
            <div v-else>{{ scope.row.label }}</div>
          </template>
        </el-table-column>
        <el-table-column prop="key" label="列名">
          <template #default="scope">
            <el-input v-model="scope.row.key" />
          </template>
        </el-table-column>
        <el-table-column label="操作" width="80px">
          <el-button-group>
            <el-button type="warning" @click="addConfig()">
              <template #icon>
                <i class="relic-iconfont relic-icon-tag" />
              </template>
            </el-button>
          </el-button-group>
        </el-table-column>
      </el-table>
      <template #header>
        <el-text>Excel列配置</el-text>
      </template>
      <template #footer>
        <el-button-group>
          <el-button @click="protocolConfigDialog = false">取消</el-button>
          <el-button type="primary" :loading="parseLoading" @click="parseXlsx">确认</el-button>
        </el-button-group>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped>
.flex-row-common {
  @apply flex flex-row justify-center items-center;
}
</style>
